/*
File:		TurretBot.cpp
Author:		Ben Feldmann
Purpose:	Class to manage game TurretBot enemies
*/

#include "TurretBot.h"
#include "SGD Wrappers/CSGD_TextureManager.h"
#include "SGD Wrappers/CSGD_Direct3D.h"
#include "SGD Wrappers/CSGD_XAudio2.h"
#include "Event.h"
#include "EventSystem.h"
#include "MessageSystem.h"
#include "DestroyEntityMessage.h"
#include "CreatePickUpMessage.h"
#include "GamePlayState.h"
#include "CreateProjectileMessage.h"
#include "Game.h"
#include "Player.h"
#include "Animation.h"
#include "AnimationSystem.h"

TurretBot::TurretBot() : target(nullptr)
{
	type = OBJ_ENEMY;
	SetHealth(200.0f);
	SetDifficulty(5);
	SetWidth(32);
	SetHeight(32);
	SetAttackTimer(0.0f);
	hide = false;
	hideTimer = 0.0f;
	beforeHitHealth = 0;
	afterHitHealth = 0;
	previousHealth = 0;
	hit = 0;
	waitTime = 1.0f;

	SetDirection(-1);

	int randParts = rand() % 2 + 1;
	SetMetal(randParts);
	SetCircuitry(randParts);
	fireSOUND = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/Enemy_Fire.wav"));
	hideSOUND = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/Turret_Hide.wav"));
	deathSOUND = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/Death_Sound.wav"));


	EventSystem::GetInstance()->RegisterClient("target_hit", this);

	maxHealth = (int)GetHealth();
}

TurretBot::~TurretBot() 
{
	EventSystem::GetInstance()->UnregisterClientAll(this);

	if( target )
		target->Release();
}

void TurretBot::Update(float elapsed) 
{
	int camx = GamePlayState::GetInstance()->GetCamX();
	int camy = GamePlayState::GetInstance()->GetCamY();
	if( GetX() > camx + 800 || GetX() + GetWidth() < camx || GetY() + GetHeight() < camy || GetY() > camy + 600 )
	{
		return;
	}

	// Update for enemy
	Enemy::Update(elapsed);

	// Health over max?
	if(GetHealth() > maxHealth)
		SetHealth((float)maxHealth);

	// Are you hit?
	/*if(hit >= 3)
	hide = true;*/

	// Check if dead
	if(GetHealth() <= 0)
	{
		CreatePickUpMessage* msg1 = new CreatePickUpMessage(0, GetMetal(), GetVectorPos(), GetType());
		MessageSystem::GetInstance()->SendMsg(msg1);
		msg1 = nullptr;

		CreatePickUpMessage* msg2 = new CreatePickUpMessage(1, GetCircuitry(), GetVectorPos(), GetType());
		MessageSystem::GetInstance()->SendMsg(msg2);
		msg2 = nullptr;

		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;

		CSGD_XAudio2::GetInstance()->SFXPlaySound(deathSOUND);

		return;
	}

	if(disabled == true)
		return;

	// Update Timer
	SetAttackTimer(GetAttackTimer() + elapsed);

	// DPS
	if(hideTimer <= 0.0f)
		previousHealth = GetHealth();

	hideTimer += elapsed;

	if(hideTimer >= waitTime)
	{
		if(1-GetHealth()/previousHealth >= 0.5)
		{
			waitTime = 3.0f;
			hide = true;
			//hit = 3;
		}
		else
		{
			waitTime = 1.0f;
			hide = false;
			//hit = 0;
		}
		hideTimer = 0.0f;
	}

	// Hide?
	/*if(hide == true)
	{
	hideTimer += elapsed;
	if(hideTimer >= 5.0f)
	{
	hideTimer = 0.0f;
	hide = false;
	hit = 0;
	}
	}*/

	if( target )
		target->Release();
	target = nullptr;

	// Get target player
	if(GamePlayState::GetInstance()->GetPlayer2() != nullptr)
	{
		float p1distance = -1, p2distance = -1;
		float p1x = -1, p2x = -1;
		float p1y = -1, p2y = -1;

		p1x = (GamePlayState::GetInstance()->GetPlayer()->GetX()-GetX())*(GamePlayState::GetInstance()->GetPlayer()->GetX()-GetX());
		p1y = (GamePlayState::GetInstance()->GetPlayer()->GetY()-GetY())*(GamePlayState::GetInstance()->GetPlayer()->GetY()-GetY());
		p1distance = sqrtf(p1x+p1y);

		p2x = (GamePlayState::GetInstance()->GetPlayer2()->GetX()-GetX())*(GamePlayState::GetInstance()->GetPlayer2()->GetX()-GetX());
		p2y = (GamePlayState::GetInstance()->GetPlayer2()->GetY()-GetY())*(GamePlayState::GetInstance()->GetPlayer2()->GetY()-GetY());
		p2distance = sqrtf(p2x+p2y);

		if(p1distance <= p2distance)
			target = GamePlayState::GetInstance()->GetPlayer();
		else
			target = GamePlayState::GetInstance()->GetPlayer2();
	}
	else
		target = GamePlayState::GetInstance()->GetPlayer();

	if(target == nullptr)
		target = GamePlayState::GetInstance()->GetPlayer();

	if( target )
		target->AddRef();
	else
		return;

	// CARDINAL
	if(target->GetY() <= GetY() && target->GetX() >= GetX()-64 && target->GetX() <= GetX()+64 && hide == false)
		SetDirection(3);
	else if(target->GetX() >= GetX() && target->GetY() >= GetY()-64 && target->GetY() <= GetY()+64 && hide == false)
		SetDirection(0);
	else if(target->GetY() > GetY() && target->GetX() >= GetX()-64 && target->GetX() <= GetX()+64 && hide == false)
		SetDirection(2);
	else if(target->GetX() < GetX() && target->GetY() >= GetY()-64 && target->GetY() <= GetY()+64 && hide == false)
		SetDirection(1);
	else if(hide == true)
		SetDirection(90);
	else
		SetDirection(-1);

	// Update Animation
	for(int i = 0; i < 5; ++i)
	{
		TurretAnimation[i].Update(elapsed);
	}

	/*for(int i = 0; i < 4; ++i)
	{
	if(GetDirection() != -1 && TurretAnimation[i].GetCurFrame() == 2 && hide == false && GetAttackTimer() >= 1.0f)
	{
	CSGD_XAudio2::GetInstance()->SFXPlaySound(fireSOUND);
	CreateProjectileMessage* msg = new CreateProjectileMessage(ENEMY, this);
	MessageSystem::GetInstance()->SendMsg(msg);
	msg = nullptr;
	SetAttackTimer(0.0f);
	}
	}*/

	// If not playing set to idle
	if(GetDirection() == -1)
	{
		for(int i = 0; i < 4; ++i)
			if(TurretAnimation[i].GetCurFrame() == 2 || TurretAnimation[i].GetCurFrame() == 1 && hide == false)
				TurretAnimation[i].SetCurFrame(0);
	}

	//if(hide == true)
	//TurretAnimation[GetDirection()].SetCurFrame(1);

	// Attack
	if(GetAttackTimer() >= 1.0f && hide == false && target->GetRoomNum() == GetRoomNum() && GetDirection() != -1)
	{
		Attack(elapsed);
	}
}

void TurretBot::Render()
{
	int camx = GamePlayState::GetInstance()->GetCamX();
	int camy = GamePlayState::GetInstance()->GetCamY();
	if( GetX() > camx + 800 || GetX() + GetWidth() < camx || GetY() + GetHeight() < camy || GetY() > camy + 600 )
	{
		return;
	}

	if(target != nullptr)
	{
		DWORD color = D3DCOLOR_ARGB(255,255,255,255);
		//if(hide == true)
		//color = D3DCOLOR_ARGB(255,255,0,0);
		if(GetPlayer()->GetRoomNum() == GetRoomNum())
		{
			/*RECT collision = {(long)(GetRect().left-GamePlayState::GetInstance()->GetCamX()), (long)(GetRect().top-GamePlayState::GetInstance()->GetCamY()),
			(long)(GetRect().left-GamePlayState::GetInstance()->GetCamX()+GetWidth()), (long)(GetRect().top-GamePlayState::GetInstance()->GetCamY()+GetHeight())};
			CSGD_Direct3D::GetInstance()->DrawRect(collision,0,0,255);*/
			if(GetDirection() != -1 && hide == false)
				TurretAnimation[GetDirection()].Render((int)GetX()- GamePlayState::GetInstance()->GetCamX(),(int)GetY()- GamePlayState::GetInstance()->GetCamY(),1.0f,color,false);
			else if(GetDirection() == 90)
				TurretAnimation[4].Render((int)GetX()- GamePlayState::GetInstance()->GetCamX(),(int)GetY()- GamePlayState::GetInstance()->GetCamY(),1.0f,color,false);
			else
				TurretAnimation[0].Render((int)GetX()- GamePlayState::GetInstance()->GetCamX(),(int)GetY()- GamePlayState::GetInstance()->GetCamY(),1.0f,color,false);
		}
	}

	Enemy::Render();
}

RECT TurretBot::GetRect()
{
	if(hide == false)
	{
		RECT tmp = (GetDirection()!=-1 ? TurretAnimation[GetDirection()].GetCollsionRect() : TurretAnimation[0].GetCollsionRect());
		int width = tmp.right;
		int height = tmp.bottom;
		tmp.top += (long)(GetY() - (GetDirection()!=-1 ? TurretAnimation[GetDirection()].GetAPoint().fY : TurretAnimation[0].GetAPoint().fY) + height);
		tmp.bottom = height + tmp.top;
		tmp.left += (long)(GetX() - (GetDirection()!=-1 ? TurretAnimation[GetDirection()].GetAPoint().fX : TurretAnimation[0].GetAPoint().fX) + (width/2));
		tmp.right = width + tmp.left;
		return tmp;
	}
	else
	{
		RECT tmp = (TurretAnimation[4].GetCollsionRect());
		int width = tmp.right;
		int height = tmp.bottom;
		tmp.top += (long)(GetY() - (TurretAnimation[4].GetAPoint().fY) + height);
		tmp.bottom = height + tmp.top;
		tmp.left += (long)(GetX() - (TurretAnimation[4].GetAPoint().fX) + (width/2));
		tmp.right = width + tmp.left;
		return tmp;
	}
}

void TurretBot::Attack(float elapsed)
{
	if( elapsed == 0 )
		elapsed = 0.001f;
	if(GetDirection() != -1)
	{
		TurretAnimation[GetDirection()].Play();

		while(TurretAnimation[GetDirection()].GetCurFrame() != 2)
		{
			TurretAnimation[GetDirection()].Update(elapsed);			
		}
		if(hide == false)
		{
			CSGD_XAudio2::GetInstance()->SFXPlaySound(fireSOUND);
			CreateProjectileMessage* msg = new CreateProjectileMessage(ENEMY, this);
			MessageSystem::GetInstance()->SendMsg(msg);
			msg = nullptr;
		}
	}

	SetAttackTimer(0.0f);
}

void TurretBot::HandleEvent(Event* thisEvent)
{
	if(thisEvent->GetParameter() != this)
		return;

	if(thisEvent->GetEventID() == "target_hit" && GetHealth() > 0 && hide == false)
	{
		void* tmpPtr = thisEvent->GetParameter2();
		float* tmp = (float*)(tmpPtr);
		SetHealth(GetHealth() - *tmp);

		if(1-GetHealth()/previousHealth >= 0.5 && GetHealth() > 0)
		{
			hide = true;
			//hit = 3;
		}

		if(hide == true)
		{
			CSGD_XAudio2::GetInstance()->SFXPlaySound(hideSOUND);
			TurretAnimation[GetDirection()].Play();
		}

		delete tmp;

		damageEm->Burst();
	}
}

void TurretBot::SetAnimation(int id[5])
{
	for(int i = 0; i < 5; ++i)
	{
		TurretAnimation[i] = *AnimationSystem::GetInstance()->GetAnimation(id[i]);
	}

	SetWidth(TurretAnimation[0].GetCollsionRect().right);
	SetHeight(TurretAnimation[0].GetCollsionRect().bottom);
}